#include <iostream>
#include <string>

#define __TEST__
#include "ring_queue.hpp"
#include "task.hpp"

#include <cstdlib>
#include <ctime>

#include <unistd.h>
#include <pthread.h>

std::string opers = "+-*/%#";

struct ThreadData
{
    std::string _name;
    RingQueue<Task>* _bq;
};

void* Consumer(void* args)
{
    // RingQueue<Task>* bq = static_cast<RingQueue<Task>*>(args);
    ThreadData* td = static_cast<ThreadData*>(args);
    while (true)
    {
        Task task = td->_bq->pop();
        task();
        std::cout << td->_name << ':';
        std::cout << " 消费了一个任务: " << task.get_result() << std::endl;
        sleep(1);
    }
    return nullptr;
}

void* Productor(void* args)
{
    sleep(3);
    ThreadData* td = static_cast<ThreadData*>(args);
    // RingQueue<Task>* bq = static_cast<RingQueue<Task>*>(args);
    while (true)
    {
        int left = rand() % 10;
        int right = rand() % 10;
        char oper = opers[rand() % opers.size()];

        Task task(left, right, oper);
        std::cout << td->_name << ':';
        std::cout << " 生产了一个任务: " << task.get_task() << std::endl;
        td->_bq->push(std::move(task));
    }
    return nullptr;
}

int main()
{
    srand((unsigned int)time(nullptr));

    RingQueue<Task>* bq = new RingQueue<Task>;

    // pthread_t c, p;
    // pthread_create(&c, nullptr, Consumer, (void*)bq);
    // pthread_create(&p, nullptr, Productor, (void*)bq);

    // pthread_join(c, nullptr);
    // pthread_join(p, nullptr);

    pthread_t c[3], p[5];
    for (int i = 0; i < 3; ++i)
    {
        ThreadData* td = new ThreadData;
        td->_bq = bq;
        td->_name = std::string("thread") + std::to_string(i);
        pthread_create(c + i, nullptr, Consumer, (void*)td);
    }
    for (int i = 0; i < 5; ++i)
    {
        ThreadData* td = new ThreadData;
        td->_bq = bq;
        td->_name = std::string("thread") + std::to_string(i + sizeof(c) / sizeof(c[0]));
        pthread_create(p + i, nullptr, Productor, (void*)td);
    }
    for (int i = 0; i < 3; ++i)
        pthread_join(c[i], nullptr);
    for (int i = 0; i < 5; ++i)
        pthread_join(p[i], nullptr);

    delete bq;

    return 0;
}